#pragma once
#include <iostream>
#include <jsoncpp/json/json.h>

const std::string Intervals_cal = " ";
const std::string Intervals_breaks_cal = "\n";

//#define _Json 1

//数据格式  len\nbody\n
std::string Encode(std::string &out)//函数构建网络数据格式
{
    std::string temp = std::to_string((out).size());
    temp += Intervals_breaks_cal;
    temp +=(out);
    temp += Intervals_breaks_cal;

    return temp;
}

// "len"\n"x op y"\nXXXXXX
// "protocolnumber"\n"len"\n"x op y"\nXXXXXX

/*std::string Decode(std::string *Network_Data)//解码函数，剥离网络数据运算部分，并做异常处理，删除处理过的部分，将剥离出的部分传出
{
    std::string ret;

    size_t pos1 = (*Network_Data).find(Intervals_breaks_cal);
    if(pos1 == std::string::npos)return "";
    std::string len_str = (*Network_Data).substr(0,pos1);
    size_t len = len_str.size();
    size_t pos2 = (*Network_Data).find(Intervals_breaks_cal,pos1+1);

    if(pos2 == std::string::npos)return "";

    if(((*Network_Data).size())<=(len+std::stoi(len_str)+2))return "";
    //printf("ret = %s\n",ret);
    ret += (*Network_Data).substr(pos1+1,std::stoi(len_str));
    //printf("ret = %s\n",ret);


    (*Network_Data).erase(0,len+std::stoi(len_str)+2);//删除已经读取到的上string内网络数据

    return ret;
}
*/
bool Decode(std::string &package, std::string *content)
{

    std::size_t pos = package.find(Intervals_breaks_cal);
    if(pos == std::string::npos) return false;
    std::string len_str = package.substr(0, pos);
    std::size_t len = std::stoi(len_str);
    
    
    // package = len_str + content_str + 2

    std::size_t total_len = len_str.size() + len + 2;
    //printf("[%s:%d] total_len:%d\n",__FILE__,__LINE__,total_len);


    if(package.size() < total_len) 
    {
        //printf("[%s:%d] decode失败\n",__FILE__,__LINE__);
        return false;
    }

    *content = package.substr(pos+1, len);
    // earse 移除报文 package.erase(0, total_len);
    package.erase(0, total_len);

    return true;
}



class Request
{
public:
    Request()
    {}
    Request(int _x,int _y,char _op)
        :x(_x)
        ,y(_y)
        ,op(_op)
    {}
    

    bool Serialization(std::string *out)//序列化构建 string
    {
#ifdef _Json
        *out += std::to_string(x);
        *out += Intervals_cal;
        *out += op;
        *out += Intervals_cal;
        *out += std::to_string(y);

        return true;
#else
        Json::Value kv;
        kv["x"] = x;
        kv["y"] = y;
        kv["op"] = op;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(kv);
        return true;
#endif
    }

    bool Deserialization(std::string &in)//x + y\n  反序列化string 构建struct
    {
#ifdef _Json
        size_t pos_left = in.find(Intervals_cal);
        if(pos_left == std::string::npos) return false;

        std::string x_part = in.substr(0,pos_left);

        size_t pos_right = in.rfind(Intervals_cal);
        if(pos_right == std::string::npos)return false;

        std::string y_part = in.substr(pos_right+1);

        op = in[pos_left+1];
        x  = std::stoi(x_part);
        y  = std::stoi(y_part);
        //printf("[%s:%d] Deserialization成功\n",__FILE__,__LINE__);

        return true;
#else
        Json::Value kv;
        Json::Reader r;
        r.parse(in, kv);

        x = kv["x"].asInt();
        y = kv["y"].asInt();
        op = kv["op"].asInt();
        return true;
#endif
    }

    ~Request()
    {}
public:
    int x;
    int y;
    char op;
};




class Response
{
public:
    Response(int _result , int _flags)
        :result(_result)
        ,Flags(_flags)
    {}

    bool Serialization(std::string *out)//序列化 result Flags
    {
#ifdef _Json
        *out+= std::to_string(result);
        *out += Intervals_cal;
        *out += std::to_string(Flags);

        return true;
#else
        Json::Value kv;
        kv["result"] = result;
        kv["Flags"] = Flags;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(kv);
        return true;
#endif
    }

    bool Deserialization(std::string &in)//result Flags  反序列化string 构建struct
    {
#ifdef _Json
        size_t pos_left = in.find(Intervals_cal);
        if(pos_left == std::string::npos) return false;

        std::string result_part = in.substr(0,pos_left);

        size_t pos_right = in.rfind(Intervals_cal);
        if(pos_right == std::string::npos)return false;

        std::string Flags_part = in.substr(pos_right+1);

        result  = std::stoi(result_part);
        Flags  = std::stoi(Flags_part);
        return true;
#else
        Json::Value kv;
        Json::Reader r;
        r.parse(in, kv);

        result = kv["result"].asInt();
        Flags = kv["Flags"].asInt();
        return true;
#endif
    }

    ~Response()
    {}
public:
    int result;
    int Flags;
};